package com.rico.gateway.config;


import com.alibaba.cloud.sentinel.SentinelProperties;
import com.alibaba.cloud.sentinel.datasource.config.NacosDataSourceProperties;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.rico.gateway.common.SentinelRuleSuffix;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Properties;
import java.util.Set;

/**
 * sentinel网关限流规则加载配置
 * 功能描述:加载网关限流规则，从nacos配置中心拉取限流规则
 *
 * @author lansent-zpj
 * @date 2020/3/29 20:31
 */


@Configuration
public class SentinelGatewayRuleLoadConfig {

    @Autowired
    private SentinelProperties sentinelProperties;


    @PostConstruct
    public void init() {
        sentinelProperties.getDatasource().entrySet().stream().filter(map -> {
            return map.getValue().getNacos() != null;
        }).forEach(map -> {
            NacosDataSourceProperties nacos = map.getValue().getNacos();
            Properties properties = new Properties();
            properties.put(PropertyKeyConst.SERVER_ADDR, nacos.getServerAddr());
            String dataId = map.getValue().getNacos().getDataId();
            //从nacos加载网关限流规则
            if (dataId.endsWith(SentinelRuleSuffix.GATEWAY_FLOW_DATA_ID_SUFFIX)) {
                NacosDataSource<Set<GatewayFlowRule>> dataSource = new NacosDataSource<>(properties,
                        nacos.getGroupId(), nacos.getDataId(), source -> JSON.parseObject(source, new TypeReference<Set<GatewayFlowRule>>() {
                }));
                GatewayRuleManager.register2Property(dataSource.getProperty());
            }
            //从nacos加载网关API分组规则
            if (dataId.endsWith(SentinelRuleSuffix.GATEWAY_API_GROUPS_DATA_ID_SUFFIX)) {
                NacosDataSource<Set<ApiDefinition>> dataSource = new NacosDataSource<>(properties,
                        nacos.getGroupId(), nacos.getDataId(),
                        source -> JSON.parseObject(source, new TypeReference<Set<ApiDefinition>>() {
                        }));
                GatewayApiDefinitionManager.register2Property(dataSource.getProperty());
            }
            //从nacos加载流控规则
            else if (dataId.endsWith(SentinelRuleSuffix.FLOW_DATA_ID_SUFFIX)) {
                ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(properties,
                        nacos.getGroupId(), nacos.getDataId(),
                        source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
                        }));
                FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
            }
            //从nacos加载降级规则
            else if (dataId.endsWith(SentinelRuleSuffix.DEGRADE_DATA_ID_SUFFIX)) {
                NacosDataSource<List<DegradeRule>> dataSource = new NacosDataSource<>(properties,
                        nacos.getGroupId(), nacos.getDataId(),
                        source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
                        }));
                DegradeRuleManager.register2Property(dataSource.getProperty());
            }
            //从nacos加载参数限流规则
            else if (dataId.endsWith(SentinelRuleSuffix.PARAM_FLOW_DATA_ID_SUFFIX)) {
                NacosDataSource<List<ParamFlowRule>> dataSource = new NacosDataSource<>(properties,
                        nacos.getGroupId(), nacos.getDataId(),
                        source -> JSON.parseObject(source, new TypeReference<List<ParamFlowRule>>() {
                        }));
                ParamFlowRuleManager.register2Property(dataSource.getProperty());
            }
            //从Nacos加载系统规则
            else if (dataId.endsWith(SentinelRuleSuffix.SYSTEM_DATA_ID_SUFFIX)) {
                NacosDataSource<List<SystemRule>> dataSource = new NacosDataSource<>(properties,
                        nacos.getGroupId(), nacos.getDataId(),
                        source -> JSON.parseObject(source, new TypeReference<List<SystemRule>>() {
                        }));
                SystemRuleManager.register2Property(dataSource.getProperty());
            }
            //从nacos加载授权规则
            else if (dataId.endsWith(SentinelRuleSuffix.AUTHORITY_DATA_ID_SUFFIX)) {
                NacosDataSource<List<AuthorityRule>> dataSource = new NacosDataSource<>(properties,
                        nacos.getGroupId(), nacos.getDataId(),
                        source -> JSON.parseObject(source, new TypeReference<List<AuthorityRule>>() {
                        }));
                AuthorityRuleManager.register2Property(dataSource.getProperty());
            }
        });
    }
}
